from pyrser.grammar import Grammar
from pyrser.parsing import resetBaseParser
from pyrser.hooks import GenericHook
from pyrser.node import *

class Lisp(GenericHook, Grammar):
      """
      s_expression ::= 	 @_ atomic_symbol 
	               | @_ list #type("list")
      ;

      list ::=	'(' 
		    @push_at("list") s_expression #func_call
		  [ @push_at("list") s_expression ]*
		')'
      ;

      atomic_symbol ::= [  
			    #identifier  #sub_type("identifier")
			  | #num  #sub_type("integer")
			  | #string #sub_type("string")
			  | 
			  [
			    [ '+' | '-' | '*' | '/' | '%' ]
			    |
			    [ "<=" | ">=" | '<' | '>' | '=' | "!="]
			    |
			    [ '!' | "&&" | '|']
			  ]
			    #sub_type("operator")
			] :atom
			#type("atom")
      ;

      """
      def __init__(self):
          super(Lisp, self).__init__(Lisp, Lisp.__doc__, globals())
	  resetBaseParser("", " \r\n\t", ";") # FIXME : don't work

      def sub_typeHook(self, oNode, sSubtype):
	  oNode['sub_type'] = sSubtype
          return True

      def typeHook(self, oNode, sType):
	  oNode['type'] = sType
          return True

      def func_callHook(self, oNode):
	  if oNode["list"][0]["type"] == "atom"\
	    and oNode["list"][0]["sub_type"] == "identifier":
	    oNode["list"][0]["sub_type"] = "func_call"
          return True


oRoot = {}
sTest = '(let ((x 20) (y 22)) (+ x y))'
print sTest
print Lisp().parse(sTest, oRoot, 's_expression')
clean_tree(oRoot, 'parent')
from pprint import pprint
pprint(oRoot)
